package task06;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static junit.framework.Assert.assertTrue;

public class FactorizerComputableTest {
    private Computable computable;
    private ExecutorService executorService;
    private long startTime;
    protected static final int CYCLES = 1_000_000;

    @Before
    public void setUp() {
//        computable = new CachedComputable(new FactorizerComputable());
//        computable = new CachedComputable2(new FactorizerComputable());
        computable = new CachedComputable3(new FactorizerComputable());
        executorService = Executors.newFixedThreadPool(32);
        startTime = System.currentTimeMillis();
    }

    @Test
    public void testInvokeCounter() {
        submitTasks();
    }

    public void submitTasks() {
        for (int i = 0; i < CYCLES; i++) {
            executorService.submit(newTask());
        }
    }

    protected Runnable newTask() {
        return new Runnable() {
            private int counter = 100;
            private final int COUNTER_MAX = 10000;
            private final int COUNTER_INCREMENT = 100;

            @Override
            public void run() {
                try {
                    if (counter > COUNTER_MAX)
                        counter = 0;
                    computable.compute(counter);
                    counter += COUNTER_INCREMENT;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
    }

    @After
    public void collectResults() throws InterruptedException {
        waitAllTasks();
        checkResults();
    }

    public void waitAllTasks() throws InterruptedException {
        executorService.shutdown();
        boolean terminated = executorService.awaitTermination(5, TimeUnit.SECONDS);
        assertTrue(terminated);
    }

    public void checkResults() {
        long time = System.currentTimeMillis() - startTime;
        System.out.println(time);
    }
}
